home *** CD-ROM | disk | FTP | other *** search
- /************** Slider.c v1.0 *********
- ******* code for a slider type control CDEF
- *******©1993 Glenn R. Howes
- ******* all rights reserved *****/
- // #include "Slider.h" included in the prefix option
-
- #include "utilities.h"
- pascal long main(short variation, ControlHandle me,
- short msg, long param)
- {
- long result = 0L;
-
-
- switch (msg)
- {
- case testCntl: // determine if mouse down is in control
- result = TestMe(me, HiWord(param), LoWord(param));
- break;
- case calcCRgns: // 24-bit means of requesting shape of control or part
- result = CalcStripRegion(me, (RgnHandle)param);
- break;
- case initCntl: // 1st message, allocate private data
- InitMe(me);
- break;
- case dispCntl: // last message, dispose private data
- if ((*me)->contrlData)
- DisposeHandle((*me)->contrlData);
- break;
- case posCntl: // given new point (and old point from the thumbCntl msg)
- // set the controls new value
- PositionMe(me, HiWord(param), LoWord(param));
- break;
- case thumbCntl: // request for info for use in dragging thumb outline
- // also gives point at which drag starts
- ProvideDragInfo(me, (ThumbInfo*)param);
- break;
- case dragCntl: // we aren't doing any custom tracking ignore
- break;
- case autoTrack: // we aren't doing any custom tracking ignore
- // result = TrackMe(me, LoWord(param));
- break;
- case calcCntlRgn: // 32-bit clean message asking for whole cntl region
- CalcRegion( me, (RgnHandle)param, FALSE);
- result = 1L;
- break;
- case calcThumbRgn: // 32-bit clean message asking for shape of thumb
- result = CalcRegion( me, (RgnHandle)param, TRUE);
- result = 1L;
- break;
- case drawCntl: // draw control or part of control
- DrawMe(me, LoWord(param));
- break;
- }
-
-
- return (result);
- }
- /******************* ProvideDragInfo ***********
- **** a mouse down has occurred in the thumb and we are
- **** asked to proide information used by the toolbox routine
- **** DragGrayRgn to confine the drag to a given rectangle
- **** the limit rect is the rect in which the region will move
- **** the slop rect is the rect in which the mouse can be and the
- **** gray outline will still be visible.
- **** Notice that I'm taking into account the position within the
- **** thumb so that the region doesn't go beyond the control****/
- void ProvideDragInfo(ControlHandle me, ThumbInfo *param)
- {
- Rect ctlRect, thumbRect;
- PrivateHandle privData;
- Point entry;
- privData = (PrivateHandle)(*me)->contrlData;
-
- // the original mousedown point is stored in the top,left corner of
- // the thumbinfo's limitRect field
-
- entry.h = param->limitRect.left;
- entry.v = param->limitRect.top;
- if (privData)
- {
- (*privData)->entryPoint.h = entry.h;
- (*privData)->entryPoint.v = entry.v;
- }
- CopyRect(&(*me)->contrlRect, &ctlRect);
- CalcThumbRects(me, (*me)->contrlValue, &thumbRect);
-
- if ((ctlRect.bottom - ctlRect.top) // if we are a vertical control
- >= (ctlRect.right - ctlRect.left))
- {
- ctlRect.bottom -= (thumbRect.bottom - entry.v);
- ctlRect.top += (entry.v - thumbRect.top);
-
- CopyRect(&ctlRect, ¶m->limitRect);
-
- param->axis = 2; // confine to vertical
- }
- else // if we are a horizontal control
- {
- ctlRect.right -= (thumbRect.right - entry.h) -1;
- ctlRect.left += (entry.h - thumbRect.left);
-
- CopyRect(&ctlRect, ¶m->limitRect);
-
- param->axis = 1; // confine to horizontal
-
- }
- InsetRect(&ctlRect, -5, -5); // make slop bigger than ctl rect
- CopyRect(&ctlRect, ¶m->slopRect);
- }
- /************ PositionMe *************
- ******** I've been dragged, with the sequence
- ****** TestMe, ProvideDragInfo, and now PositionMe
- ****** so the delta values are changes from the original mousedown *****/
- void PositionMe(ControlHandle me, short deltaV, short deltaH)
- {
- Point newPoint;
-
- MapValue2Point(me, (*me)->contrlValue, &newPoint);
- newPoint.v += deltaV;
- newPoint.h += deltaH;
-
- MapPt2Value(me, &newPoint, &(*me)->contrlValue);
- DrawMe(me, 0);
- }
- /************ MapPt2Value *****************
- ***** given a point within the control, map it to a control value
- ******/
- void MapPt2Value(ControlHandle me, Point *aPoint, short *value)
- {
- Rect ctlRect;
- short width, height, thumbLen, halfThumb;
- long min, max, locValue;
-
- CopyRect(&(*me)->contrlRect, &ctlRect);
- min = (*me)->contrlMin;
- max = (*me)->contrlMax;
-
- width = ctlRect.right - ctlRect.left;
- height = ctlRect.bottom - ctlRect.top;
-
- thumbLen = CalcThumbLen(&ctlRect);
- halfThumb = thumbLen /2;
-
- if (width > height)
- {
- ctlRect.right -= halfThumb;
- ctlRect.left += halfThumb;
- width -= thumbLen;
- if (ctlRect.right < aPoint->h) aPoint->h = ctlRect.right;
- else if (ctlRect.left > aPoint->h) aPoint->h = ctlRect.left;
-
- locValue = min + ((max-min)*(aPoint->h-ctlRect.left))/width;
- }
- else
- {
- ctlRect.bottom -= halfThumb;
- ctlRect.top += halfThumb;
- height -= thumbLen;
- if (ctlRect.bottom < aPoint->v) aPoint->v = ctlRect.bottom;
- else if (ctlRect.top > aPoint->v) aPoint->v = ctlRect.top;
-
- locValue = min + ((max-min)*(ctlRect.bottom-aPoint->v))/height;
- }
- *value = locValue;
- }
- /*********** MapValue2Point *********
- ******* given a control value, convert it to a point within
- ******* the control corresponding to where the center of the thumb
- ******* must be **********/
- void MapValue2Point(ControlHandle me, short value, Point *aPoint)
- {
- Rect ctlRect;
- long width, height;
- long min, max;
- short thumbLen, halfThumb;
- CopyRect(&(*me)->contrlRect, &ctlRect);
- min = (*me)->contrlMin;
- max = (*me)->contrlMax;
-
- thumbLen = CalcThumbLen(&ctlRect);
- halfThumb = thumbLen /2;
-
- width = ctlRect.right - ctlRect.left;
- height = ctlRect.bottom - ctlRect.top;
-
- if (value > max)
- value = max;
- else if (value < min)
- value = min;
-
- if (width > height) // horizontal control
- {
- width -= thumbLen;
- aPoint->h = ctlRect.left + halfThumb + (width*value)/(max-min);
- aPoint->v = ctlRect.top + height/2;
- }
- else
- {
- height -= thumbLen;
- aPoint->v = ctlRect.bottom - halfThumb -(height * value)/(max-min);
- aPoint->h = ctlRect.left + width/2;
- }
- }
-
- /************* CalcStripRegion *******
- ******* when in 24-bit mode, we will get a region handle whose
- ******* 31st bit is used to indicate if the app wants the region
- ******* of the thumb (on) or the whole control (off).
- ******* We are supposed to strip off the bit and return the
- ******* calculated region ******/
- long CalcStripRegion(ControlHandle me, RgnHandle theRegion)
- {
- char calcThumb;
- if (Using32Bit()) // WHY IS THIS GETTING CALLED¿
- {
- return (CalcRegion(me, theRegion, FALSE));
- }
- else
- {
- calcThumb = (long)theRegion >> 31L; // getting high bit, on = calc thumb
- theRegion = (RgnHandle)(0x7FFFFFFFL & (long)theRegion);
- // stripping out high bit only see tech note “joy of 32 bit clean”
- return (CalcRegion(me, theRegion, calcThumb)); // calc the region
- }
- }
- /*************** CalcRegion ******
- ******* figure the region of the control, or the thumb if the
- ******* calcThumb parameter is non-zero **********/
- long CalcRegion(ControlHandle me, RgnHandle theRegion, char calcThumb)
- {
- RgnHandle myRegion;
- Rect ctlRect, thumbRect;
- short diameter;
- myRegion = NewRgn();
- if (myRegion)
- {
- OpenRgn();
- CopyRect(&(*me)->contrlRect, &ctlRect);
- diameter = CalcRounding(&ctlRect);
- if (calcThumb)
- {
- CalcThumbRects(me, (*me)->contrlValue, &thumbRect);
- FrameRoundRect(&thumbRect, diameter,diameter);
- }
- else
- {
- FrameRoundRect(&ctlRect, diameter, diameter);
- }
-
- CloseRgn(myRegion);
- InsetRgn(myRegion, -1, -1); // make it a little bigger to take into account
- // width of lines
- UnionRgn(theRegion, myRegion, theRegion);
- DisposeRgn(myRegion);
- }
-
- return ((long)theRegion);
- }
- /************ TestMe ****************
- ******* is the point within the control, and if so,
- ******* what part, there are 3 parts: thumb, pageup,
- pagedown **********/
- long TestMe(ControlHandle me, short v, short h)
- {
- Point testPoint;
- long result = 0L;
- Rect ctlRect, whiteRect, grayRect, roundThumb;
-
- testPoint.h = h; testPoint.v = v;
-
- if(PtInRect(testPoint, &(*me)->contrlRect) && (*me)->contrlHilite < 255)
- // quick determination of (mouse in rect and control undimmed)
- {
- CopyRect(&(*me)->contrlRect, &ctlRect);
- CalcGrayRect(me, &grayRect, &whiteRect);
- CalcThumbRects(me,(*me)->contrlValue, &roundThumb);
- if (PtInRect(testPoint, &roundThumb))
- {
- result = inThumb;
- }
- else if (PtInRect(testPoint, &grayRect))
- {
- result = inPageUp;
- }
- else
- {
- result = inPageDown;
- }
- }
- return (result);
- }
- /*************** DrawMe **********
- ******* Draw the control or the control's thumb *****/
- void DrawMe(ControlHandle me, short part)
- {
- Rect grayRect, whiteRect, thumbRect, tempRect;
- PenState oldState;
- PrivateHandle privData;
- RgnHandle oldRegion = 0L, thumbRegion = 0L, ctlRegion =0L;
- short diameter;
-
- GetPenState(&oldState);
- PenNormal();
- privData = (PrivateHandle)(*me)->contrlData;
- CalcGrayRect(me, &grayRect, &whiteRect);
- CalcThumbRects(me, (*me)->contrlValue, &thumbRect);
-
- switch (part)
- {
- case 255: // change in dimming
- EraseRect(&grayRect);
- case 0: // draw whole thing
- EraseRect(&whiteRect);
- DrawMyFrame(me,&grayRect);
- DrawMyIndicator(me, &thumbRect);
- break;
- case 129: // redraw generic indicator
- // I'm using the regions to stop the flashing of drawing
- // the gray rect and then drawing the white thumb over it
- oldRegion = NewRgn();
- thumbRegion = NewRgn();
- ctlRegion = NewRgn();
- if (ctlRegion && thumbRegion && oldRegion && privData)
- {
- diameter = CalcRounding(&(*me)->contrlRect);
- GetClip(oldRegion);
- CopyRect(&thumbRect, &tempRect);
- // InsetRect(&tempRect, -2,-2);
- OpenRgn();
- FrameRoundRect(&(*me)->contrlRect, diameter, diameter);
- CloseRgn(ctlRegion);
- OpenRgn();
- FrameRoundRect(&thumbRect, diameter, diameter);
- CloseRgn(thumbRegion);
- XorRgn(ctlRegion, thumbRegion, thumbRegion);
- SetClip(thumbRegion);
- CleanOldThumb(me, &thumbRect);
- SetClip(ctlRegion);
- DrawMyIndicator(me, &thumbRect);
- SetClip(oldRegion);
- }
- else // we had a memory allocation problem, draw whole thing
- {
- EraseRect(&whiteRect);
- DrawMyFrame(me,&grayRect);
- DrawMyIndicator(me, &thumbRect);
- }
- if (thumbRegion) DisposeRgn(thumbRegion);
- if (ctlRegion) DisposeRgn(ctlRegion);
- if (oldRegion) DisposeRgn(oldRegion);
- break;
- default:
- case inPageUp:
- case inPageDown:
- break;
- }
- if (privData)
- (*privData)->oldValue = (*me)->contrlValue;
- SetPenState(&oldState);
- }
- /*************** CleanOldThumb *************
- ***** We've gotten a message to draw the thumb, which
- ***** implies we have to eradicate the old thumb *******/
- void CleanOldThumb(ControlHandle me, Rect *thumbRect)
- {
- PrivateHandle privData;
- short oldValue, currValue;
- short diameter;
- Rect grayRect, ctlRect, oldThumb, whiteRect;
- Boolean upAndDown;
- Pattern grayPattern;
-
- privData = (PrivateHandle)(*me)->contrlData; // privData has already been tested
- currValue = (*me)->contrlValue;
- oldValue = (*privData)->oldValue;
-
- //if (currValue == oldValue) return;
-
- (*me)->contrlValue = oldValue;
- CalcGrayRect(me, &grayRect, &whiteRect);
- (*me)->contrlValue = currValue;
-
- CopyRect(&(*me)->contrlRect, &ctlRect);
- diameter = CalcRounding(&ctlRect);
- upAndDown = ((ctlRect.right - ctlRect.left) <= (ctlRect.bottom - ctlRect.top));
-
- CalcThumbRects(me, oldValue, &oldThumb);
- GetIndPattern(grayPattern, 0, 1);// black
- PenPat(&grayPattern);
-
- if (oldValue > currValue)
- {
- if (upAndDown)
- {
- oldThumb.bottom = thumbRect->bottom;
- }
- else
- {
- oldThumb.left = thumbRect->left;
- }
- FillRoundRect(&oldThumb, diameter, diameter, &grayPattern);
- }
- else
- {
- if (upAndDown)
- {
- oldThumb.top = thumbRect->top;
- }
- else
- {
- oldThumb.right = thumbRect->right;
- }
- EraseRoundRect(&oldThumb, diameter, diameter);
- }
- FrameRoundRect(&ctlRect, diameter, diameter);
- }
- /********** DrawMyIndicator ************
- ******* Draw the thumb, the thumbRect must be previously
- ******* calculated ******/
- void DrawMyIndicator(ControlHandle me, Rect *thumbRect)
- {
- Rect ctlRect;
- Boolean useColorQD, dimmed = FALSE;
- RGBColor newColor, oldColor;
- Pattern grayPattern;
- Boolean upAndDown;
- short diameter;
- PrivateHandle privData;
-
- privData = (PrivateHandle)(*me)->contrlData;
-
- if ((*me)->contrlMin >= (*me)->contrlMax) dimmed = TRUE;
- if ((*me)->contrlHilite == 255) dimmed = TRUE;
-
-
- if (!dimmed)
- {
- CopyRect(&(*me)->contrlRect, &ctlRect);
- diameter = CalcRounding (&ctlRect);
-
-
- // calculate the rectangles used in drawing
- useColorQD = UseColorQD(me, thumbRect);
- // start actual drawing
- if(useColorQD && privData)
- {
- GetForeColor(&oldColor);
- RGBForeColor(&(*privData)->thumbColor); // real medium gray
- GetIndPattern(grayPattern, 0, 1);// standard black for fill
- FillRoundRect(thumbRect, diameter, diameter, &grayPattern);
- RGBForeColor(&oldColor);
- }
- else
- {
- GetIndPattern(grayPattern, 0, 4);// standard gray for fill
- FillRoundRect(thumbRect, diameter, diameter, &grayPattern);
- }
- FrameRoundRect(thumbRect, diameter, diameter);
- }
- }
- /***************** CalcThumbRects ******
- **** should be CalcThumbRect, just figure what the bounding rect of
- *** the thumb should be given the value *******/
- void CalcThumbRects(ControlHandle me, short value,
- Rect *roundThumb)
- {
- long width, height, thumbLen;
- Point valuePoint;
- Rect ctlRect;
-
- CopyRect(&(*me)->contrlRect, &ctlRect);
- CopyRect(&ctlRect, roundThumb);
-
- height = ctlRect.bottom - ctlRect.top;
- width = ctlRect.right - ctlRect.left;
-
- MapValue2Point(me, value, &valuePoint);
- thumbLen = CalcThumbLen(&ctlRect);
- // calculate the rectangles used in drawing
- if (height >= width)
- {
- roundThumb->top = valuePoint.v - thumbLen/2;
- roundThumb->bottom = roundThumb->top+thumbLen;
-
- }
- else
- {
- roundThumb->right = valuePoint.h + thumbLen/2;
- roundThumb->left = roundThumb->right - thumbLen;
- }
- }
- /********** CalcThumbLen *********
- **** figure how high or wide the thumb should be (given
- **** that some moron might have made the control too small ***/
- short CalcThumbLen(Rect *ctlRect)
- {
- short height, width;
- short result;
- height = ctlRect->bottom - ctlRect->top;
- width = ctlRect->right - ctlRect->left;
- if (width > height)
- {
- result = (width > 20)?20:width;
- }
- else
- {
- result = (height > 20)?20:height;
- }
- return (result);
- }
- /********* DrawMyFrame **********
- ******* Draw the black portion of the control (pageup)
- ******* and frame the whole thing ********/
- void DrawMyFrame(ControlHandle me, Rect *grayRect)
- {
- Rect ctlRect;
- Boolean useColorQD, dimmed = FALSE;
- RGBColor newColor, oldColor;
- Pattern grayPattern;
- PrivateHandle privData;
- short min, max, diameter;
- privData = (PrivateHandle)(*me)->contrlData;
-
- CopyRect(&(*me)->contrlRect, &ctlRect);
- useColorQD = UseColorQD(me, &ctlRect);
- min = (*me)->contrlMin;
- max = (*me)->contrlMax;
- diameter = CalcRounding (&ctlRect);
- if (min >= max)
- {
- dimmed = TRUE;
- }
- if ((*me)->contrlHilite == 255) dimmed = TRUE;
-
- if (!dimmed)
- {
- GetIndPattern(grayPattern, 0, 1);// standard black for frame and top region
- FillRoundRect(grayRect,diameter, diameter, &grayPattern);
- PenPat(&grayPattern);
- }
- if(useColorQD && privData)
- {
- GetForeColor(&oldColor);
- RGBForeColor(&(*privData)->frameColor);
- FrameRoundRect(&ctlRect, diameter, diameter);
- RGBForeColor(&oldColor);
- }
- else
- FrameRoundRect(&ctlRect, diameter, diameter);
- }
- /*********** CalcGrayRect
- ***** figure out the rectangle which enclose the pageup and pagedown
- ***** parts of the control (they meet in the middle of the thumb) ***/
- void CalcGrayRect(ControlHandle me, Rect *grayRect, Rect *whiteRect)
- {
- long height, width, value, max, min;
- Point valuePoint;
- short thumbLen, halfThumb;
-
-
- value = (*me)->contrlValue;
- min = (*me)->contrlMin;
- max = (*me)->contrlMax;
- if (value > max) // too big, who let this in?
- value = max;
- else if (value < min) // too small
- value = min;
- MapValue2Point(me,value, &valuePoint);
-
- CopyRect(&(*me)->contrlRect, grayRect);
- CopyRect(grayRect, whiteRect);
- thumbLen = CalcThumbLen(grayRect);
- halfThumb = thumbLen /2;
- width = grayRect->right - grayRect->left;
- height = grayRect->bottom - grayRect->top;
- if (width > height) // we are going side to side
- {
- grayRect->left = valuePoint.h - halfThumb;
- whiteRect->right = valuePoint.h;
- }
- else
- { // halfThumb is because quickdraw sort of bales out
- // when round rects are small
- grayRect->bottom = valuePoint.v + halfThumb;
- whiteRect->top = valuePoint.v;
- }
- }
- /******* CalcRounding *******
- ****** are we big enough to use round rectangles
- if so use 16 diameter rounding, if not use square corners ****/
- short CalcRounding(Rect *ctlRect)
- {
- short width, height;
- width = ctlRect->right - ctlRect->left;
- height = ctlRect->bottom - ctlRect->top;
- if (width > height)
- {
- if (width > 64)
- return (16);
- }
- else
- {
- if (height > 64)
- return (16);
- }
- return (0);
- }
-
- /******** InitMe ********
- ****** allocate my global memory, test for color and load color table
- ****** information ****/
- void InitMe(ControlHandle me)
- {
- PrivateHandle privDataH;
- AuxCtlHandle acHndl;
- CCTabHandle tableH;
- short tabLen;
- RGBColor *tempColor;
- privDataH = (PrivateHandle)NewHandleClear(sizeof(Private));
- if (privDataH)
- {
- if ((*privDataH)->useColorQD = TestForColor())
- {// we are using color, find the highlight color
- tempColor = &(*privDataH)->frameColor;
- tempColor->red = tempColor->blue = tempColor->green = 0; // black
- tempColor = &(*privDataH)->thumbColor;
- tempColor->blue = tempColor->green = tempColor->red = 30583; // gray
- GetAuxCtl(me, &acHndl);
- if (acHndl)
- {
- tableH = (*acHndl)->acCTable;
- tabLen = (*tableH)->ctSize;
- while(tabLen >= 0)
- {
- if ((*tableH)->ctTable[tabLen].value == cFrameColor)
- {
- BlockMove(&(*tableH)->ctTable[tabLen].rgb,
- &(*privDataH)->frameColor, sizeof(RGBColor));
- }
- /* else if ((*tableH)->ctTable[tabLen].value == cThumbColor)
- {
- BlockMove(&(*tableH)->ctTable[tabLen].rgb,
- &(*privDataH)->thumbColor, sizeof(RGBColor));
- } */
- tabLen--;
- }
- }
- }
- // we need to know if we can call GetDeviceList to tell whether
- // or not our control is on a deep color screen
- (*privDataH)->devicesAvailable = TrapAvailable(0xAA29);
-
- (*privDataH)->oldValue = (*me)->contrlValue;
- }
- (*me)->contrlData = (Handle)privDataH;
- }
-
-
-